import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.converter.IntegerStringConverter;
import java.io.*;
import java.util.List;
import java.util.regex.Pattern;

public class Main extends Application {

    private final Button mFileBtn = new Button("获\r\n取\r\n文\r\n件");

    private final TextField inputTv = new TextField();

    private final TextField mFileMaxSize = new TextField();//单个文件最大大小
    private final TextField mSwapText = new TextField();//换行关键字

    @Override
    public void start(Stage stage) throws Exception {
        AnchorPane root = new AnchorPane();

        initTv(root);

        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.initStyle(StageStyle.DECORATED);
        stage.setTitle("十六进制格式显示工具");
        stage.setHeight(400);
        stage.setWidth(800);
        stage.show();
    }

    private void initTv(AnchorPane root) {
        inputTv.setPrefHeight(70);

        inputTv.setEditable(false);
        inputTv.setText("可直接把文件拉进文本框或点击右侧按钮");

        mFileBtn.setPrefHeight(70);
        mFileBtn.setPrefWidth(50);

        mFileBtn.setOnAction(event -> {
            FileChooser chooser = new FileChooser();
            chooser.setTitle("请选择要打开的文件");
            //筛选文件类型
            chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文件类型","*.apk"));

            File file = chooser.showOpenDialog(new Stage());
            //如果不选文件直接关闭窗口的话，返回值为空
            if(file != null){
                inputTv.setText(file.getAbsolutePath());
                analyseFile();
            }
        });


        AnchorPane.setTopAnchor(mFileBtn,30.0);
        AnchorPane.setRightAnchor(mFileBtn,10.0);

        AnchorPane.setTopAnchor(inputTv,30.0);
        AnchorPane.setRightAnchor(inputTv,70.0);
        AnchorPane.setLeftAnchor(inputTv,10.0);

        Label label1 = new Label("单个文件大小限制(当文件过大时可分为多个文件，单位为k)：");

        AnchorPane.setTopAnchor(label1,125.0);
        AnchorPane.setLeftAnchor(label1,10.0);

        AnchorPane.setTopAnchor(mFileMaxSize,120.0);
        AnchorPane.setLeftAnchor(mFileMaxSize,350.0);

        TextFormatter<Integer> formatter = new TextFormatter<>(
                new IntegerStringConverter(),
                -1,
                c -> Pattern.matches("\\d*", c.getText()) ? c : null );

        mFileMaxSize.setTextFormatter(formatter);

        Label label2 = new Label("换行关键字（如H264数据可以用00 00 00 01）：");
        AnchorPane.setTopAnchor(label2,155.0);
        AnchorPane.setLeftAnchor(label2,10.0);

        AnchorPane.setTopAnchor(mSwapText,150.0);
        AnchorPane.setLeftAnchor(mSwapText,350.0);


        //监听文件拖动文本框内
        inputTv.setOnDragExited(event -> {
            List<File> files = event.getDragboard().getFiles();
            if (files!=null&&!files.isEmpty()){
                inputTv.setText(files.get(0).getAbsolutePath());
                analyseFile();
            }
        });

        root.getChildren().addAll(inputTv,mFileBtn,label1, mFileMaxSize,label2,mSwapText);
    }

    private void analyseFile() {
        String input = inputTv.getText();
        if (input == null||input.trim().length() == 0){
            showAlter("提示","文件名不能为空");
            return;
        }

        File f = new File(input);
        if (!f.exists()||!f.isFile()){
            showAlter("提示","文件不存在"+f.getAbsolutePath());
            return;
        }


        try {
            InputStream in = new FileInputStream(f);

            int maxLen = Integer.parseInt(mFileMaxSize.getText());
            int FILE_MAX_SIZE;

            if (maxLen > 0){
                FILE_MAX_SIZE = maxLen*1024;
            }else{
                FILE_MAX_SIZE = -1;
            }

            int fileCount = 1;//分文件：第一个文件

            OutputStream out = null;
            if (f.length() > FILE_MAX_SIZE){
                out = new FileOutputStream(new File(f.getAbsolutePath()+"("+fileCount+").txt"));
            }else{
                out = new FileOutputStream(new File(f.getAbsolutePath()+".txt"));
            }

            byte[] buf = new byte[1024];
            int len;

            int writeSize = 0;

            String wrap = mSwapText.getText().trim();

            while ((len = in.read(buf)) > 0) {
                byte[] data = toHexStr(buf,len,wrap).getBytes();
                writeSize += data.length;
                if (FILE_MAX_SIZE > 0&&writeSize > FILE_MAX_SIZE){
                    fileCount++;
                    writeSize = 0;
                    out = new FileOutputStream(new File(f.getAbsolutePath()+"("+fileCount+").txt"));
                }

                out.write(data, 0, data.length);
            }
            in.close();
            out.close();

            showAlter("提示","转换完毕");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String toHexStr(byte[] data,int len,String wrap){
        StringBuilder builder = new StringBuilder();
        for (int i = 0;i<len;i++){
            byte b = data[i];

            String hex = Integer.toHexString(b&0xFF);
            if (hex.length() == 1){
                builder.append("0");
            }

            builder.append(hex);
            builder.append(" ");
        }

        if (wrap.length() > 0){
            int index = -1;
            while ((index = builder.indexOf(wrap,index)) > -1){
                builder.insert(index,"\r\n");
                index += index+wrap.length();
            }
        }

        return builder.toString();
    }

    private void showAlter(String title,String msg){
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setTitle("提示");
        alert.setContentText(msg);
        alert.setHeaderText(title);
        alert.showAndWait();
    }


    public static void main(String[] args) {
        launch();
    }
}
